package com.kmzx.one.project.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.github.binarywang.wxpay.bean.order.WxPayMpOrderResult;
import com.kmzx.one.common.constants.Constants;
import com.kmzx.one.common.constants.UpMode;
import com.kmzx.one.common.enums.CommonEnums;
import com.kmzx.one.common.exceptions.NoSuchObjectException;
import com.kmzx.one.common.exceptions.OrderErrorException;
import com.kmzx.one.common.exceptions.ParameterNullException;
import com.kmzx.one.common.utils.DateTimeUtils;
import com.kmzx.one.common.utils.HttpClientUtil;
import com.kmzx.one.common.utils.StringUtils;
import com.kmzx.one.common.utils.UUIDGenerator;
import com.kmzx.one.project.config.wx.WxPayUtils;
import com.kmzx.one.project.entity.*;
import com.kmzx.one.project.events.PatchProdEvent;
import com.kmzx.one.project.mapper.*;
import com.kmzx.one.project.net.CartParam;
import com.kmzx.one.project.net.OnceParam;
import com.kmzx.one.project.net.OrderParam;
import com.kmzx.one.project.others.common.ExpressArrayInfo;
import com.kmzx.one.project.others.common.FeeData;
import com.kmzx.one.project.others.dso.CartOrderDso;
import com.kmzx.one.project.others.dso.ProdJoinDiscount;
import com.kmzx.one.project.others.dso.ProductExtraInfo;
import com.kmzx.one.project.others.dso.UserOrderDso;
import com.kmzx.one.project.others.dso.UserRankMoney;
import com.kmzx.one.project.others.dto.FreightInfo;
import com.kmzx.one.project.others.dto.OrderBackInfo;
import com.kmzx.one.project.others.dto.UserOrderFinalInfo;
import com.kmzx.one.project.others.dto.UserOrderMoreInfo;
import com.kmzx.one.project.others.dto.UserOrderOutInfo;
import com.kmzx.one.project.others.dto.UserProfitInfo;
import com.kmzx.one.project.others.dto.UserRankInfo;
import com.kmzx.one.project.others.vos.ExpressInfos;
import com.kmzx.one.project.service.UserOrderService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.ApplicationContext;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@Service
public class UserOrderServiceImpl implements UserOrderService {

    @Value("${aliyun.market.appcode}")
    private String appCode;
    @Value("${aliyun.express.address}")
    private String expressAddress;

    @Autowired
    StringRedisTemplate stringRedisTemplate;

    @Autowired
    private UserOrderMapper userOrderMapper;

    @Autowired
    private UserRankMapper userRankMapper;

    @Autowired
    private FastUpMapper fastUpMapper;

    @Autowired
    private UserGrowthDetailMapper userGrowthDetailMapper;

    @Autowired
    private UserPayMapper userPayMapper;

    @Autowired
    private OrderBillMoneyMapper orderBillMoneyMapper;

    @Autowired
    private UserAddressMapper userAddressMapper;

    @Autowired
    private UserCartMapper userCartMapper;

    @Autowired
    private ProductMapper productMapper;

    @Autowired
    private WarehouseMapper warehouseMapper;

    @Autowired
    CustomerMapper customerMapper;

    @Autowired
    SimpleMapper simpleMapper;

    @Autowired
    WxUserMapper wxUserMapper;

    @Autowired
    private UserProfitMapper userProfitMapper;

    @Autowired
    private UserExchangeRateMapper userExchangeRateMapper;

    @Autowired
    private RedisTemplate<String, Object> stringObjectRedisTemplate;

    @Autowired
    ApplicationContext applicationContext;


    @Override
    public List<UserOrderOutInfo> findUserAllOrder(String userId, Integer pageNum, Integer pageSize, Integer kinds) throws Exception {
        pageNum = (pageNum - 1) * pageSize;
        long version41 = 1585708507701l;
        List<UserOrderDso> subOrders;
        if (kinds != null)
            kinds = kinds - 1;

        if (kinds == 0 || kinds == 1 || kinds == 2) {
            subOrders = userOrderMapper.selectUserOrderAllPager(userId, pageNum, pageSize, kinds);
        } else if (kinds == 3) {
            subOrders = userOrderMapper.selectUserOrderAllPager(userId, pageNum, pageSize, 4);
        } else {
            subOrders = userOrderMapper.selectUserOrderAllPager2(userId, pageNum, pageSize);
        }
        ArrayList<UserOrderOutInfo> details = new ArrayList<>();
        if (subOrders.size() != 0) {
            for (UserOrderDso subOrder : subOrders) {
                String allInfo = subOrder.getAllInfo();
                // 商品名 | 货号 | 属性
                String[] info = allInfo.split("\\|");
                subOrder.setProdName(info[0]);
                subOrder.setProdAttr(info[2]);
                BigDecimal tariffFee = subOrder.getTariffFee();
                BigDecimal expressFee = subOrder.getExpressFee();
                if (tariffFee == null) {
                    subOrder.setTariffFee(BigDecimal.ZERO);
                }
                if (expressFee == null) {
                    subOrder.setExpressFee(BigDecimal.ZERO);
                }

                BigDecimal prodDiscount = subOrder.getProdDiscount();
                if (prodDiscount == null) {
                    subOrder.setProdDiscount(BigDecimal.ONE);
                }

                BigDecimal currPrice = subOrder.getCurrPrice();
                if (currPrice == null) {
                    subOrder.setCurrPrice(subOrder.getProdPrice().multiply(subOrder.getProdDiscount()));
                }
                BigDecimal account = subOrder.getAccount();
                if (account == null) {
                    subOrder.setAccount(BigDecimal.ZERO);
                }
                BigDecimal repository = subOrder.getRepository();
                if (repository == null) {
                    subOrder.setRepository(BigDecimal.ZERO);
                }
//                -------------------------deleted
                if (subOrder.getTradeType() == null) {
                    subOrder.setTradeType(2);
                }
            }
            Map<String, List<UserOrderDso>> map = subOrders.stream().collect(Collectors.groupingBy(UserOrderDso::getOrderId));

            Set<String> set = map.keySet();
            for (String s : set) {
                UserOrderOutInfo outInfo = new UserOrderOutInfo();
                outInfo.setOrderId(s);
                List<UserOrderDso> userOrderDtos = map.get(s);
                BigDecimal zero = BigDecimal.ZERO;
                userOrderDtos.forEach(st -> zero.add(st.getProdPrice().multiply(BigDecimal.valueOf(st.getProdNum()))));

                long count = userOrderDtos.stream().map(lt -> lt.getProdNum()).reduce((a, b) -> a + b).get();
                outInfo.setCounts(count);
                outInfo.setDetail(userOrderDtos);
                outInfo.setTime(userOrderDtos.get(0).getTimeStr());
                outInfo.setTimeStamp(userOrderDtos.get(0).getCreateTime().getTime());
                BigDecimal billSub = userOrderDtos.stream().map(lv -> lv.getBillMoney()).reduce((a, b) -> a.add(b)).get();
                outInfo.setBillMoney(billSub);
                outInfo.setStates(userOrderDtos.get(0).getStates());
                BigDecimal billEnd = userOrderDtos.stream().map(lv -> lv.getEndMoney()).reduce((a, b) -> a.add(b)).get();
                outInfo.setEndMoney(userOrderDtos.get(0).getUpEndMoney());
                outInfo.setTotalMoney(billEnd);
                outInfo.setTradeType(userOrderDtos.get(0).getTradeType());
                outInfo.setOrderDiscount(userOrderDtos.get(0).getOrderDiscount());

                outInfo.setTariffFee(userOrderDtos.stream().map(ll -> ll.getTariffFee()).reduce((c, d) -> c.add(d)).get());
                outInfo.setExFee(userOrderDtos.stream().map(ll -> ll.getExpressFee()).reduce((c, d) -> c.add(d)).get());

                Integer tradeType = userOrderDtos.get(0).getTradeType();
                if (tradeType != null) {
                    if (tradeType == 1) {
                        outInfo.setTariffFee(BigDecimal.ZERO);
                        outInfo.setExFee(userOrderDtos.get(0).getGateExpressFee());
                    }
                }

                BigDecimal gateExpressFee = userOrderDtos.get(0).getGateExpressFee();
                if (gateExpressFee == null) {
                    gateExpressFee = BigDecimal.ZERO;
                }
//                BigDecimal ecoMoney = gateExpressFee.add(billSub).subtract(billEnd);
                BigDecimal ecoMoney = BigDecimal.ZERO.add(billSub).subtract(billEnd);
//                        .add(outInfo.getExFee()).add(outInfo.getTariffFee());
                outInfo.setEcoMoney(ecoMoney);

                BigDecimal orderDiscount = outInfo.getOrderDiscount();
                if (outInfo.getTimeStamp() < version41) {
                    if (outInfo.getEndMoney().compareTo(BigDecimal.ZERO) == 0) {
                        outInfo.setRepository(outInfo.getTotalMoney());
                    }
                }
                if (orderDiscount != null) {
                    if (orderDiscount.compareTo(BigDecimal.ONE) < 0) {
                        outInfo.setOrderDiscount(orderDiscount.multiply(BigDecimal.TEN));
                    }
                    if (orderDiscount.compareTo(BigDecimal.ONE) == 0) {
                        outInfo.setOrderDiscount(BigDecimal.TEN);
                    }
                } else {
                    BigDecimal discounts = billEnd.divide(billSub, RoundingMode.HALF_UP);
                    if (discounts != null) {

                        if (discounts.compareTo(BigDecimal.ONE) == 0) {
                            outInfo.setOrderDiscount(BigDecimal.TEN);
                        } else {
                            // 包含邮费的
                            outInfo.setOrderDiscount(BigDecimal.TEN);
                        }

                        if (discounts.compareTo(BigDecimal.ONE) < 0) {
                            outInfo.setOrderDiscount(discounts.multiply(BigDecimal.TEN));
                        }
                    }
                }

                BigDecimal account = outInfo.getAccount();
                BigDecimal repository = outInfo.getRepository();
                if (account == null) {
                    outInfo.setAccount(BigDecimal.ZERO);
                }
                if (repository == null) {
                    outInfo.setRepository(BigDecimal.ZERO);
                }
                BigDecimal sumAccount = userOrderDtos.get(0).getAccount();
                outInfo.setAccount(sumAccount);
                BigDecimal sumRepo = userOrderDtos.get(0).getRepository();
                outInfo.setRepository(sumRepo);
                //--------------------------deleted-----------------------------
                if (outInfo.getTradeType() == 2) {
                    outInfo.setExFee(BigDecimal.ZERO);
                }
                details.add(outInfo);
            }
            details.sort(Comparator.comparing(UserOrderOutInfo::getTimeStamp).reversed());
        }
        return details;
    }

    @Override
    public UserOrderMoreInfo findUserOrderDetail(String orderId) throws Exception {
        UserOrderMoreInfo moreInfo = userOrderMapper.selectUserOrderDetail(orderId);

        if (moreInfo != null) {
            List<UserOrderDso> subDetail = userOrderMapper.selectUserOrderSubDetail(orderId);
            for (UserOrderDso dso : subDetail) {
                String allInfo = dso.getAllInfo();
                String[] threeInfo = allInfo.split("\\|");
                String attr = threeInfo[2];
                String name = threeInfo[0];
                BigDecimal currPrice = dso.getCurrPrice();
                if (currPrice == null) {
                    dso.setCurrPrice(dso.getProdPrice());
                }
                dso.setProdName(name);
                dso.setProdAttr(attr);
            }
            moreInfo.setTotalMoney(subDetail.stream().map(mp -> mp.getEndMoney()).reduce((a, b) -> a.add(b)).get());
            moreInfo.setDetail(subDetail);
            moreInfo.setExpressCompany(subDetail.get(0).getExpressCompany());
            moreInfo.setExpressCode(subDetail.get(0).getExpressCode());
//            String username = moreInfo.getUsername();
//            String nickName = moreInfo.getNickName();
            /**
             *  <view class="row address_item" bindtap='goMail'>
             *
             *     <view class="fl col">
             *       <view class="row mail_name">
             *         <text class="fl">{{ orderData.nickName }}  {{ orderData.mobile }} </text>
             *         <image class="fr gprs_img" src='/images/gprs.png'></image>
             *       </view>
             *       <view class="row address_box">
             *         <text class="fl address_title">{{ orderData.allInfo }} </text>
             *       </view>
             *     </view>
             *   </view>
             */
//            moreInfo.setNickName(username);
//            moreInfo.setUsername(username);

            BigDecimal orderDiscount = moreInfo.getOrderDiscount();

            if (orderDiscount != null) {
                if (orderDiscount.compareTo(BigDecimal.ONE) == 0) {
                    moreInfo.setOrderDiscount(BigDecimal.TEN);
                }
                if (orderDiscount.compareTo(BigDecimal.ONE) < 0) {
                    moreInfo.setOrderDiscount(orderDiscount.multiply(BigDecimal.TEN));
                }

            } else {
                BigDecimal totalMoney = moreInfo.getTotalMoney();
                BigDecimal billMoney = moreInfo.getBillMoney();
                BigDecimal discounts = totalMoney.divide(billMoney);
                if (discounts != null) {
                    if (discounts.compareTo(BigDecimal.ONE) < 0) {
                        moreInfo.setOrderDiscount(discounts.multiply(BigDecimal.TEN));
                    }
                    if (discounts.compareTo(BigDecimal.ONE) == 0) {
                        moreInfo.setOrderDiscount(BigDecimal.TEN);
                    }
                }

            }
            if (moreInfo.getExFee() == null) {
                moreInfo.setExFee(BigDecimal.ZERO);
            }
            if (moreInfo.getTariffFee() == null) {
                moreInfo.setTariffFee(BigDecimal.ZERO);
            }

            Integer tradeType = moreInfo.getTradeType();
            if (tradeType != null) {
                if (tradeType == 1) {
                    moreInfo.setExFee(moreInfo.getGateExpressFee());
                    moreInfo.setTariffFee(BigDecimal.ZERO);
                }
            }
            BigDecimal ecoMoney = moreInfo.getBillMoney().subtract(moreInfo.getTotalMoney());
//                    .add(moreInfo.getExFee()).add(moreInfo.getTariffFee());
            moreInfo.setEcoMoney(ecoMoney);
            return moreInfo;
        } else {
            throw new ParameterNullException("数据为空");
        }
    }

    @Override
    @Transactional
    public Integer doCancelOrder(String userId, String orderId, String reason) throws Exception {
        UserOrder order = userOrderMapper.selectById(orderId);
        Integer states = order.getStates();
        if (states == 0) {
            Date date = new Date();
            order.setStates(5);
            order.setUpdateTime(date);
            int i = userOrderMapper.updateByIdSelective(order);
            int batchUpdateSubOrder = userOrderMapper.batchUpdateSubOrder(orderId, 5, date);


            BigDecimal repoMoney = order.getPayMoney();
            BigDecimal profitMoney = order.getProfitMoney();

            if (repoMoney != null && repoMoney.compareTo(BigDecimal.ZERO) > 0) {
                FreightInfo freight = customerMapper.selectUserFreight(order.getUserId());
                String tempId = freight.getTempId();
                UserPay userPay = new UserPay();
                userPay.setMoney(freight.getMoney().add(repoMoney));
                userPay.setUpdateTime(date);
                userPay.setId(tempId);
                userPayMapper.updateByIdSelective(userPay);

            }

            if (profitMoney != null && profitMoney.compareTo(BigDecimal.ZERO) > 0) {
                UserProfitInfo userProfitInfo = customerMapper.selectUserProfit(order.getUserId());
                UserProfit userProfit = new UserProfit();
                userProfit.setId(userProfitInfo.getTemps());
                userProfit.setUpdateTime(date);
                userProfit.setProfitMoney(userProfitInfo.getCanPay().add(profitMoney));
                userProfitMapper.updateByIdSelective(userProfit);
            }


            List<WarehouseDetail> warehouseDetails = warehouseMapper.selectWarehouseInfoByOrderId(orderId, 0);

            List<Warehouse> warehouseList = new ArrayList<>();
            if (!CollectionUtils.isEmpty(warehouseDetails)) {
                for (WarehouseDetail warehouseDetail : warehouseDetails) {
                    // 取消了
                    Integer order_down_number = warehouseDetail.getProductNumber();
                    warehouseDetail.setUpdateTime(date);
                    warehouseDetail.setStates(1);
                    Warehouse warehouse = warehouseMapper.selectWarehouseByBatchSkuId(warehouseDetail.getAttributeWithCategoryId(), warehouseDetail.getWarehouseBatch());
                    if (warehouse != null) {
                        Integer old_number = warehouse.getNowNumber();
                        warehouse.setUpdateTime(date);
                        warehouse.setNowNumber(old_number + order_down_number);
                        warehouseList.add(warehouse);
                    }
                }
                // 将库存明细表回撤状态
                warehouseMapper.batchUpdateWarehouseDetail(warehouseDetails);
                // 将库存表回填
                warehouseMapper.batchUpdateWarehouse(warehouseList);
            }

            return i + batchUpdateSubOrder;
        } else {
            throw new ParameterNullException("该订单状态异常,取消失败!");
        }
    }

    @Override
    public Map<String, Object> findOrderExpressInfo(String orderId) throws Exception {

        Map<String, String> info = userOrderMapper.selectSubOrderExpressInfo(orderId);
        if (!CollectionUtils.isEmpty(info)) {
//            ExpressInfos express = findExpress(info.get("subsCodes"), info.get("expressCodes"));
            ExpressInfos express = findNewExpressInfo(orderId, info.get("subId"), info.get("express_number"), info.get("subsCodes"), info.get("expressCodes"));
            HashMap<String, Object> map = new HashMap<>();
            map.put("content", express.getCnt());
            map.put("expressCodes", info.get("expressCodes"));
            map.put("expressName", info.get("expressName"));
            String icon = customerMapper.findExpressIcon(info.get("express_number"));
            if (icon != null) {
                map.put("expressIcon", icon);
            } else {
                map.put("expressIcon", customerMapper.findExpressIcon("shunfeng"));
            }
            return map;
        } else {
            throw new NoSuchObjectException(CommonEnums.NO_Express_Info.getCode(), CommonEnums.NO_Express_Info.getMsg());
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Integer doExchangeOrder(String orderId, int what, String reason, String[] pics) throws Exception {
        UserOrderSubs subs = userOrderMapper.selectSubsOrderById(orderId);
        if (subs == null) {
            throw new ParameterNullException("暂无该订单");
        }

        Integer states = subs.getStates();
        if (states != 3) {
            throw new ParameterNullException("该订单状态异常");
        }
        subs.setId(orderId);
        subs.setReason1(reason);
        subs.setUpdateTime(new Date());
        subs.setTime1(subs.getUpdateTime());
        int length = pics.length;
        if (length > 3) {
            throw new ParameterNullException("图片数量已超限!");
        }
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < length; i++) {
            if (StringUtils.isNotEmpty(pics[i]) && i != 2) {
                sb.append(pics[i]).append(",");
            } else if (StringUtils.isNotEmpty(pics[i])) {
                sb.append(pics[i]);
            }
        }
        String picsUrls = sb.toString();
        subs.setApplyPic(picsUrls);
        //  0,换货,1,退货
        String ordersId = subs.getOrdersId();
        UserOrder userOrder = new UserOrder();
        userOrder.setId(ordersId);
        if (what == 0) {
            subs.setStates(9);
            userOrder.setStates(9);
        }
//        else {
//            LockProfitEvent lockProfitEvent = new LockProfitEvent(subs.getUserId(), "退货");
//            lockProfitEvent.setMoney(subs.getSubBill());
//            lockProfitEvent.setOrderId(subs.getOrdersId());
//            lockProfitEvent.setSubOrderId(subs.getId());
//            applicationContext.publishEvent(lockProfitEvent);
//            subs.setStates(6);
//            userOrder.setStates(6);
//        }
        int main = userOrderMapper.updateByIdSelective(userOrder);
        int sub = userOrderMapper.updateSubsByIdSelective(subs);
        if (main > 0 && sub > 0) {
            return 1;
        } else {
            throw new OrderErrorException(502, "订单换货异常");
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Integer doConfirmOrder(String orderId) throws Exception {
        UserOrder order = userOrderMapper.selectById(orderId);
        Date date = new Date();
        order.setStates(3);
        order.setUpdateTime(date);
        order.setRemark("用户确认");
        int main = userOrderMapper.updateByIdSelective(order);
        int sub = userOrderMapper.batchUpdateSubOrder(orderId, 3, date);
        if (main > 0 && sub > 0) {
            return 1;
        } else {
            throw new OrderErrorException(502, "订单换货异常");
        }
    }

    @Override
    public UserOrderFinalInfo doGenOrder(OrderParam orderParam) throws Exception {
        int i = orderParam.checkWhich();
        if (i == 0) {
            throw new ParameterNullException("参数为空,不支持交易");
        }
        if (i == 1) {
            UserOrderFinalInfo cart = dealWithCart(orderParam.getCart());
            return cart;
        }
        if (i == 2) {
            UserOrderFinalInfo once = dealWithOnce(orderParam.getOnce());
            return once;
        }
        return null;
    }

    @Autowired
    WxPayUtils wxPayUtils;

    @Override
    public Object doPayOrder(String orderId, String userId) throws Exception {
        WxUser wxUser = wxUserMapper.selectById(userId);
        String openId = wxUser.getOpenId();
        UserOrder order = userOrderMapper.selectById(orderId);
        Integer states = order.getStates();
        if (states == 0) {
            List<UserGrowthDetail> details = simpleMapper.selectUserGrowthDetail(userId, orderId, UpMode.SelfBuy);
            if (!CollectionUtils.isEmpty(details)) {
                UserGrowthDetail detail = details.get(0);
                Double growthValue = detail.getGrowthValue();
                BigDecimal end = BigDecimal.valueOf(growthValue);
                BigDecimal endMoney = order.getEndMoney();
                // 够了
                if (end.compareTo(endMoney) >= 0) {

                } else {
                    // 0待支付 1待发货 2 待收货 3已完成 4 支付失败 5 已取消 6待退款 7已退款 8 退款失败 9 待审核 10 审核成功 11 审核失败
                    WxPayMpOrderResult orderResult = wxPayUtils.payOrder(UUIDGenerator.generate(), openId, order.getEndMoney().subtract(end), order.getOrdersCodes(), "快美甄选,支付:" + order.getOrdersCodes(), orderId);
//            orderResult.get
                    logger.info("订单支付返回数据:{}", orderResult);
                    return orderResult;
                }
            } else {
                // 0待支付 1待发货 2 待收货 3已完成 4 支付失败 5 已取消 6待退款 7已退款 8 退款失败 9 待审核 10 审核成功 11 审核失败
                WxPayMpOrderResult orderResult = wxPayUtils.payOrder(UUIDGenerator.generate(), openId, order.getEndMoney(), order.getOrdersCodes(), "快美甄选,支付:" + order.getOrdersCodes(), orderId);
//            orderResult.get
                logger.info("订单支付返回数据:{}", orderResult);
                return orderResult;
            }
            return null;
        } else {
            if (states == 1) {
                throw new ParameterNullException("该订单已支付,待发货!");
            }
            if (states == 2) {
                throw new ParameterNullException("该订单已发货,待收货!");
            }
            if (states == 3) {
                throw new ParameterNullException("该订单已完成,请勿多付款!");
            }
            if (states == 4) {
                throw new ParameterNullException("该订单支付失败,请勿重试!");
            }
            if (states == 5) {
                throw new ParameterNullException("该订单已取消,请勿重试!");
            } else {
                throw new ParameterNullException("该订单异常,请勿重试!");
            }
        }
    }

    @Override
    public UserOrder findUserOrderByCodes(String orderNo) throws Exception {
        UserOrder order = userOrderMapper.selectById(orderNo);
        if (order != null) {
            return order;
        } else {
            throw new NoSuchObjectException(401, "订单不存在");
        }
    }

    @Override
    public Integer doDelOrder(String orderId, String userId) throws Exception {
        UserOrder order = userOrderMapper.selectById(orderId);
        if (order != null) {
            Date date = new Date();
            order.setUpdateTime(date);
            order.setDeleted(1);
            int update = userOrderMapper.updateByIdSelective(order);
            return update;
        } else {
            throw new NoSuchObjectException(401, "订单不存在");
        }
    }

    @Override
    public OrderBackInfo findSubOrderBack(String orderId) throws Exception {
        UserOrderSubs subs = userOrderMapper.selectSubsOrderById(orderId);
        if (subs != null) {
            String applyPic = subs.getApplyPic();
            String[] allPics = applyPic.split(",");

            OrderBackInfo info = new OrderBackInfo();
            info.setOrderId(orderId)
                    .setPics(Arrays.asList(allPics))
                    .setReason(subs.getReason1())
                    .setReply(subs.getReason2())
                    .setStates(subs.getStates())
                    .setTimes(DateTimeUtils.formatLocalDate(subs.getTime1()));
            return info;
        } else {
            throw new NoSuchObjectException(401, "订单不存在");
        }
    }

    @Override
    public UserOrderFinalInfo doGenFastOrder(OrderParam orderParam) throws Exception {
        OnceParam once = orderParam.getOnce();
        String skuId = once.getSkuId();
        String userId = once.getUserId();
        // 库存量
        long buyNum = once.getNum();
        String prodId = once.getProdId();
        String addressId = once.getAddressId();
        int account = once.getAccount();
        int usePay = once.getUse();

        Product product = productMapper.selectProdById(prodId);
        UserAddress address = userAddressMapper.selectById(addressId);

        UserRankInfo rankInfo = userRankMapper.selectUserRankTabs(userId);
        Integer ranks = fastUpMapper.selectSkuRank("", skuId);
        if (ranks == null) {
            throw new ParameterNullException("商品异常!");
        } else {
            if(rankInfo.getRankNum()>ranks){
                throw new ParameterNullException("您的等级不符合,下单失败!");
            }
        }


        if (product == null || (product != null && product.getStates() == 1)) {
            throw new ParameterNullException("该商品已下架");
        }

        List<Warehouse> warehouseList = warehouseMapper.selectWarehouseInfo(skuId);
        if (CollectionUtils.isEmpty(warehouseList)) {
            throw new ParameterNullException("该商品不存在");
        }
        int totalStore = warehouseList.stream().mapToInt(s -> s.getNowNumber()).sum();
        if (totalStore == 0) {
            throw new NoSuchObjectException(402, "暂无库存 o(╥﹏╥)o");
        }
        if (totalStore < buyNum) {
            throw new NoSuchObjectException(402, "数量超过库存啦");
        }

        // 商品信息
        AttributeWithCategory prodAttribute = productMapper.selectAttributeWithCategoryById(skuId);

        HashMap<String, String[]> two = new HashMap<>();
        HashMap<String, String> three = new HashMap<>();
        HashMap<String, String> four = new HashMap<>();

        String allIds = prodAttribute.getAllAttributeValuesId();
        String[] split = allIds.split(",");
        List<String> allNameIds = Arrays.asList(split);

        two.put(prodAttribute.getId(), split);

        List<ProductAttributeValues> names = productMapper.selectProdNamesByAllIds(allNameIds);
        names.forEach(name -> {
            String cateImg = name.getCateImg();
            three.put(name.getId(), name.getCategoryValue());
            if (cateImg != null && cateImg != "") {
                four.put(name.getId(), name.getCateImg());
            }
        });
        String[] combineIds = two.get(once.getSkuId());
        // 名称
        StringBuilder sb = new StringBuilder();
        StringBuilder img = new StringBuilder();
        for (int ls = 0; ls < combineIds.length; ls++) {
            String imgUrls = four.get(combineIds[ls]);
            if (imgUrls != null) {
                img.append(imgUrls);
            }
            String s = three.get(combineIds[ls]);
            if (s != null) {
                if (ls != combineIds.length - 1) {
                    sb.append(s + "、");
                } else {
                    sb.append(s);
                }
            }
        }
        String prodName = product.getProductName();
        Integer inOrOut = product.getInOrOut();


        // 原始价格
        // todo 总价=数量*价格
        BigDecimal originMoney = prodAttribute.getPrice().multiply(BigDecimal.valueOf(buyNum));
        BigDecimal upPrice = productMapper.selectFastProdBySku(skuId);
        int fastGrade = productMapper.selectFastGradeBySkuId(skuId);

        if (upPrice == null) {
            throw new NoSuchObjectException(402, "数量超过库存啦");
        }
        originMoney = upPrice.multiply(BigDecimal.valueOf(buyNum));
        BigDecimal billMoney = originMoney;
        // 关税
        BigDecimal rateMoney = BigDecimal.ZERO;

        List<ProductExtraInfo> productExtraInfos = productMapper.selectProdExtraInfo("");
        // 运费
        BigDecimal exFee = BigDecimal.ZERO;

        if (inOrOut == 2) {
            // todo  计算商品的 运费,关税
            if (!CollectionUtils.isEmpty(productExtraInfos)) {
                // todo
                List<ProductExtraInfo> collect = productExtraInfos.stream().filter(ll -> ll.getTradeType() == 2 && ll.getProvinceCode().equals(address.getCode())).collect(Collectors.toList());
                if (collect != null && collect.size() > 0) {
                    ProductExtraInfo otherFee = collect.get(0);
                    // todo  关税
                    double chargesNumber = otherFee.getChargesNumber();
                    // todo 运费
                    BigDecimal chargesPrice = otherFee.getChargesPrice();
                    // todo 关税
                    rateMoney = BigDecimal.valueOf(chargesNumber).multiply(billMoney);
                    exFee = chargesPrice;

                }
            }
        } else if (inOrOut == 0) {
            // todo  计算商品的 运费,关税
            if (!CollectionUtils.isEmpty(productExtraInfos)) {
                // todo
                List<ProductExtraInfo> collect = productExtraInfos.stream().filter(ll -> ll.getTradeType() == 1 && ll.getProvinceCode().equals(address.getCode())).collect(Collectors.toList());
                if (collect != null && collect.size() > 0) {
                    ProductExtraInfo otherFee = collect.get(0);
                    // todo  关税
                    double chargesNumber = otherFee.getChargesNumber();
                    // todo 运费
                    BigDecimal chargesPrice = otherFee.getChargesPrice();
                    // todo 关税
                    rateMoney = BigDecimal.valueOf(chargesNumber).multiply(billMoney);
                    exFee = chargesPrice;

                }
            }
        }


        String orderId = UUIDGenerator.generate();
        Date date = new Date();
        // todo 有用户等级
        UserOrderSubs subOrder = new UserOrderSubs();

        subOrder.setId(UUIDGenerator.generate()).setUserId(userId).setCreateTime(date).setUpdateTime(date).setDeleted(0).setStates(0);
        subOrder.setTariffFree(rateMoney);
        subOrder.setProductId(prodId).setOrdersId(orderId).setProductNum((int) buyNum).setRealName("").setIdCard("");
        subOrder.setSubBill(billMoney);
        subOrder.setSubEnd(billMoney);
        subOrder.setExpressFree(exFee);
        subOrder.setProductDiscount(0.0);


        subOrder.setProductRemark(prodName + "|" + prodAttribute.getProfiles() + "|" + sb.toString());
        subOrder.setProductPrice(prodAttribute.getPrice());
        subOrder.setProdCurrentPrice(upPrice);
        subOrder.setSpecificImg(img.toString());
        // fast generate sub codes
        subOrder.setSubsCodes(UUIDGenerator.generateOrderNo("FGSC"));

        UserOrder order = new UserOrder();
        order.setId(orderId).setCreateTime(date).setUpdateTime(date).setAddressId(addressId).setDeleted(0).setStates(0);
        order.setUserId(userId).setUserDiscount(1.0).setPayMoney(BigDecimal.ZERO).setProfitMoney(BigDecimal.ZERO);
        order.setTariffFree(rateMoney);
        order.setGateExpressFee(exFee);
        order.setTradeType(inOrOut).setYunfei(exFee).setOrderDiscount(1.0);

        //  fast  generate
        order.setOrdersCodes(UUIDGenerator.generateOrderNo("FG"));
        order.setProdNum((int) buyNum).setFastOrder(1).setFastGrade(fastGrade);
        order.setBillMoney(billMoney);
        order.setEndMoney(billMoney);

        //保存订单

        // 消耗库存
        // 次数
        int times = warehouseList.size();
        ArrayList<WarehouseDetail> warehouseDetails = new ArrayList<>();

        for (int i = 0; i < times; i++) {
            Warehouse warehouse = warehouseList.get(i);
            Integer nowNumber = warehouse.getNowNumber();
            WarehouseDetail warehouseDetail = new WarehouseDetail();
            warehouseDetail.setOrdersId(orderId);
            warehouseDetail.setProductId(prodId);
            warehouseDetail.setProductName(prodName);
            warehouseDetail.setProfiles(prodAttribute.getProfiles());
            warehouseDetail.setAttributeWithCategoryId(prodAttribute.getId());
            warehouseDetail.setOrderCodes(order.getOrdersCodes());
            warehouseDetail.setSubsCodes(subOrder.getSubsCodes());
            warehouseDetail.setAttributeWithCategoryName(sb.toString());
            warehouseDetail.setProductMoney(prodAttribute.getPrice());
            warehouseDetail.setWarehouseBatch(warehouse.getWarehouseBatch());
            warehouseDetail.setCreateTime(date);
            warehouseDetail.setNowCost(warehouse.getNowCost());
            warehouseDetail.setUpdateTime(date);
            warehouseDetail.setStates(0);
            if (nowNumber >= buyNum) {
                int st = (int) buyNum;
                warehouse.setNowNumber(nowNumber - st);
                warehouseDetail.setId(UUIDGenerator.generate());
                warehouseDetail.setProductNumber((int) buyNum);
                warehouseDetails.add(warehouseDetail);
                break;
            } else {
                buyNum = buyNum - nowNumber;
                warehouseDetail.setProductNumber(nowNumber);
                warehouseDetail.setId(UUIDGenerator.generate());
                warehouseDetails.add(warehouseDetail);
                warehouse.setNowNumber(0);
            }
        }

        BigDecimal truthPayMoney = order.getEndMoney();

        UserOrderFinalInfo uof = new UserOrderFinalInfo();
        uof.setOrderId(orderId).setOrderNo(order.getOrdersCodes())
                .setOrderMoney(truthPayMoney).setNeedPay(0).setNeedMoney(truthPayMoney);
        String cre = DateTimeUtils.formatLocalDate(order.getCreateTime());
        uof.setCreateTime(cre);


        // 我的账户
        UserProfit userProfitL1 = new UserProfit();

        if (account == 1) {

            // 勾选余额付款
            UserProfitInfo userProfitInfo = customerMapper.selectUserProfit(userId);
            if (userProfitInfo != null) {
                BigDecimal canPay = userProfitInfo.getCanPay();
                // 充足,账户钱够用
                if (truthPayMoney.compareTo(canPay) <= 0) {
                    // 已经使用了货仓余额
                    userProfitL1.setId(userProfitInfo.getTemps());
                    userProfitL1.setProfitMoney(canPay.subtract(truthPayMoney));
                    userProfitL1.setUpdateTime(date);


                    order.setEndMoney(BigDecimal.ZERO);
                    order.setStates(1);
                    subOrder.setStates(1);


                    uof.setNeedPay(1);
                    uof.setNeedMoney(BigDecimal.ZERO);
                    uof.setOrderMoney(BigDecimal.ZERO);


                    StringBuilder stringBuilder = new StringBuilder(Constants.rewardOrderPrefix);
                    stringBuilder.append(order.getUserId() + "_" + inOrOut).append(",")
                            .append(truthPayMoney).append(",")
                            .append(order.getId()).append(",")
                            .append(date.getTime()).append(",")
                            .append("profit");


                    UserGrowthDetail growInfo = new UserGrowthDetail();
                    growInfo.setCreateTime(date);
                    growInfo.setId(UUIDGenerator.generate());
                    growInfo.setGrowthValue(truthPayMoney.doubleValue());
                    growInfo.setUpMode(UpMode.SelfBuy);
                    growInfo.setOrdersId(orderId);
                    order.setFinishTime(date);
                    growInfo.setUserId(userId);
                    growInfo.setFromUserId(userId);
                    order.setProfitMoney(truthPayMoney);
                    order.setPayMoney(BigDecimal.ZERO);
                    userGrowthDetailMapper.insert(growInfo);
                    userProfitMapper.updateByIdSelective(userProfitL1);

                    // 订单倒计时,15秒后计算 等级收益
                    stringObjectRedisTemplate.opsForValue().set(stringBuilder.toString(), stringBuilder.toString(), 15, TimeUnit.SECONDS);
                    saveOrderAndSubsAndCart(order, subOrder, warehouseList, warehouseDetails);
                    return uof;
                }
            }
        }
        uof.setNeedMoney(truthPayMoney);
        uof.setOrderMoney(truthPayMoney);
        // 任何都没勾选
        ValueOperations<String, String> opsForValue = stringRedisTemplate.opsForValue();
        opsForValue.set(Constants.lifestyleOrderPrefix + orderId, orderId, 6, TimeUnit.HOURS);
        saveOrderAndSubsAndCart(order, subOrder, warehouseList, warehouseDetails);
        return uof;
    }

    /**
     * 购物车结算的情形
     *
     * @param cartParam
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public UserOrderFinalInfo dealWithCart(CartParam cartParam) {

        String userId = cartParam.getUserId();
        List<String> cartIds = cartParam.getIds();
        String addressId = cartParam.getAddressId();
        String idCard = cartParam.getIdCard();
        int profit = cartParam.getUse();
        int account = cartParam.getAccount();
        if (CollectionUtils.isEmpty(cartIds)) {
            throw new ParameterNullException("购物车商品不存在");
        }

        cartIds = cartIds.stream().distinct().collect(Collectors.toList());


        int len = cartIds.size();
        List<CartOrderDso> myCart = userCartMapper.collectUserCartByIds2(cartIds);
        if (CollectionUtils.isEmpty(myCart)) {
            throw new ParameterNullException("购物车中物品不存在");
        } // 商品总数
        long prodtotal = 0l;
        prodtotal = myCart.stream().mapToLong(st -> st.getProdNum()).sum();
        if (prodtotal == 0) {
            throw new NoSuchObjectException(402, "一丁点儿数量都没 o(╥﹏╥)o");
        }

        // 提前准备
        List<String> one = new ArrayList<>(myCart.size());
        List<String> prodIds = new ArrayList<>(myCart.size());

        for (CartOrderDso dso : myCart) {
            Integer right = dso.getProdStates();
            if (right == 1) {
                throw new NoSuchObjectException("该商品已下架");
            }
            Integer awcStates = dso.getAwcStates();
            if (awcStates == 1) {
                throw new NoSuchObjectException("该商品已下架");
            }
            one.add(dso.getAttrId());
            prodIds.add(dso.getProdId());
        }


        List<Warehouse> warehouseList = warehouseMapper.selectWarehouseInfos(one);
        Map<String, List<Warehouse>> repoWithWarehouse = warehouseList.stream().collect(Collectors.groupingBy(Warehouse::getAttributeWithCategoryId));
        for (CartOrderDso dso : myCart) {
            String attrId = dso.getAttrId();
            List<Warehouse> warehouseList1 = repoWithWarehouse.get(attrId);

            int totalStore = warehouseList1.stream().mapToInt(s -> s.getNowNumber()).sum();
            if (totalStore == 0) {
                throw new NoSuchObjectException(402, "暂无库存 o(╥﹏╥)o");
            }
            if (totalStore < dso.getProdNum()) {
                throw new NoSuchObjectException(402, "数量超过库存啦");
            }
        }

        List<AttributeWithCategory> allPrice = productMapper.selectAttributePrice(one);
        if (CollectionUtils.isEmpty(allPrice)) {
            throw new ParameterNullException("购物车下单失败");
        }

        List<ProdJoinDiscount> skuJoinDiscount = productMapper.selectProductSkuJoinDiscount(one);

        HashMap<String, String[]> two = new HashMap<>();
        HashMap<String, String> three = new HashMap<>();
        HashMap<String, String> four = new HashMap<>();
        HashMap<String, BigDecimal> five = new HashMap<>();
        Map<String, List<ProdJoinDiscount>> six = new HashMap<>();
        ArrayList<String> allNameIds = new ArrayList<>();


        ArrayList<UserOrderSubs> subOrders = new ArrayList<>();
        Date date = new Date();

        // pre order_id
        String orderId = UUIDGenerator.generate();
        String orderCodes = UUIDGenerator.generateOrderNo("PG");
        ArrayList<Warehouse> warehouses = new ArrayList<>();
        ArrayList<WarehouseDetail> warehouseDetails = new ArrayList<>();

        UserRankMoney userRank = userRankMapper.selectUserRankAndMoney(userId);
        UserAddress address = userAddressMapper.selectById(addressId);


        allPrice.forEach(category -> {
            String allIds = category.getAllAttributeValuesId();
            String[] split = allIds.split(",");
            two.put(category.getId(), split);
            five.put(category.getId(), category.getPrice());
            for (String s : split) {
                allNameIds.add(s);
            }
        });

        if (!CollectionUtils.isEmpty(skuJoinDiscount)) {
            Map<String, List<ProdJoinDiscount>> map = skuJoinDiscount.stream().collect(Collectors.groupingBy(ProdJoinDiscount::getSkuId));
            six = map;
        }

        List<ProductAttributeValues> names = productMapper.selectProdNamesByAllIds(allNameIds);
        for (int i = 0; i < names.size(); i++) {
            three.put(names.get(i).getId(), names.get(i).getCategoryValue());
            String cateImg = names.get(i).getCateImg();
            if (cateImg != null && !"".equals(cateImg)) {
                four.put(names.get(i).getId(), names.get(i).getCateImg());
            }
        }


        // todo 原始价格
        BigDecimal originMoney = BigDecimal.ZERO;
        // todo 折后价
        BigDecimal discountMoney = originMoney;
        // todo 海外商品的原价
        BigDecimal seaOriginMoney = originMoney;

        BigDecimal seaDiscountMoney = discountMoney;

        BigDecimal billMoney = originMoney;

        BigDecimal seaBillMoney = originMoney;

        BigDecimal soRealMoney = originMoney;

        // todo 求商品的关税,运费  charges_number,关税,charges_price 运费
        List<ProductExtraInfo> productExtraInfos = productMapper.selectProdExtraInfo("");
        List<FeeData> data = productMapper.selectProductFeeData2();

        BigDecimal exFee = BigDecimal.ZERO;
        BigDecimal totalGateFee = BigDecimal.ZERO;
        BigDecimal orderDiscount = BigDecimal.ONE;
        int isOut = 0;

        BigDecimal totalExpressFee = BigDecimal.ZERO;
        BigDecimal totalOutGateFee = BigDecimal.ZERO;
        int totalExpressUse = 1;
        int totalOutGateUse = 1;
        for (CartOrderDso le : myCart) {
            // todo 商品,海外:1  国内:0,保税仓:2
            Integer ss = le.getInOrOut();
            isOut = ss;
            // 数量
            long prodNum = le.getProdNum();

            BigDecimal currPrice = le.getAttrPrice();

            BigDecimal cp2 = le.getAttrPrice();
            // todo 商品价格= 价格* 数量
            BigDecimal middleMoney = le.getAttrPrice().multiply(BigDecimal.valueOf(prodNum));
            billMoney = billMoney.add(middleMoney);
            originMoney = originMoney.add(middleMoney);
            // todo 商品的打折信息
            String attrId = le.getAttrId();

            List<ProdJoinDiscount> prodJoinDiscounts = six.get(attrId);

            if (prodJoinDiscounts != null && prodJoinDiscounts.size() > 0) {
                BigDecimal discountNum = prodJoinDiscounts.get(0).getDiscountNum();
                // todo 商品的打折种类,
                // todo  1,固定金额
                // todo  0,折扣率
                Integer discountCate = prodJoinDiscounts.get(0).getDiscountCate();

                if (discountNum != null) {
                    billMoney = billMoney.subtract(middleMoney);
                    if (discountCate == 1) {
                        le.setDiscountNum(-1.0);
                        middleMoney = discountNum.multiply(BigDecimal.valueOf(prodNum));
                        currPrice = discountNum;
                        cp2 = discountNum;
                    } else {
                        le.setDiscountNum(discountNum.doubleValue());
                        middleMoney = middleMoney.multiply(discountNum);
                        currPrice = currPrice.multiply(discountNum);
                        cp2 = cp2.multiply(discountNum);
                    }
                    billMoney = billMoney.add(middleMoney);
                }
            }


            //  有用户等级
            if (userRank != null) {
                // 用户折扣
                BigDecimal userDiscount = userRank.getUserDiscount();
                // 海外折扣
                BigDecimal seaRankRate = userRank.getSeaRankRate();
                // 等级返利率
                BigDecimal rankInterest = userRank.getRankInterest();


                // 不论是否为0,都计算
                middleMoney = middleMoney.multiply(userDiscount);

                if (rankInterest.compareTo(BigDecimal.ZERO) > 0) {
                    if (ss != 1) {
                        middleMoney = middleMoney.multiply(rankInterest);
                        orderDiscount = rankInterest;
                        currPrice = currPrice.multiply(rankInterest);
                    } else {
                        middleMoney = middleMoney.multiply(seaRankRate);
                        currPrice = currPrice.multiply(seaRankRate);
                        orderDiscount = seaRankRate;
                    }
                }
            }
            le.setMi(middleMoney);
            le.setcP(currPrice);
            le.setCp2(cp2);


            // todo  计算商品的 运费,关税
            if (!CollectionUtils.isEmpty(productExtraInfos)) {
                // todo

                ProductExtraInfo otherFee = productExtraInfos.get(0);
                // todo  关税
                double chargesNumber = otherFee.getChargesNumber();
                // todo 运费
                BigDecimal chargesPrice = otherFee.getChargesPrice();
                // todo 关税
                BigDecimal gateFee = middleMoney.multiply(BigDecimal.valueOf(chargesNumber));
                if (ss == 0) {
                    // 国内货
                    gateFee = BigDecimal.ZERO;

                } else if (ss == 2) {
                    // 保税仓
                    List<ProductExtraInfo> collect = productExtraInfos.stream().filter(lt -> lt.getTradeType() == 2 && lt.getProvinceCode().equals(address.getCode())).collect(Collectors.toList());
//                    gateFee = middleMoney.multiply()
                    if (collect != null && collect.size() > 0) {

                        ProductExtraInfo productExtraInfo = collect.get(0);
                        if (collect != null && collect.size() > 0) {
                            gateFee = BigDecimal.valueOf(productExtraInfo.getChargesNumber()).multiply(middleMoney);
                        }
                        exFee = productExtraInfo.getChargesPrice();
                        le.setExFee(exFee);

                        int toUse = productExtraInfo.getToUse();
                        int toUse2 = productExtraInfo.getToUse2();
                        if (toUse == 0) {
                            totalExpressFee = productExtraInfo.getChargesPrice();
                            totalExpressUse = 0;
                            le.setToUE(0);
                        }
                        if (toUse2 == 0) {
                            totalOutGateFee = totalOutGateFee.add(gateFee);
                            totalOutGateUse = 0;
                            le.setToUG(0);
                        }
                    }

                }
                // todo 运费
//                BigDecimal exsFee = chargesPrice.multiply(BigDecimal.valueOf(prodNum));
                le.setExFee(chargesPrice);
                le.setTariffFee(gateFee);
                // 所有的关税和
                totalGateFee = totalGateFee.add(gateFee);
            }
            discountMoney = discountMoney.add(middleMoney);
        }


        seaOriginMoney = originMoney;
        seaDiscountMoney = discountMoney;
        soRealMoney = discountMoney;
        if (totalExpressUse == 0) {
            discountMoney = discountMoney.add(totalExpressFee);
        }
        if (totalOutGateUse == 0) {
            discountMoney = discountMoney.add(totalOutGateFee);
        }

        if (isOut == 1) {
            // 海外物品
            if (!CollectionUtils.isEmpty(data)) {
                FeeData feeData = data.get(0);
                if (originMoney.compareTo(feeData.getFullMoney()) < 0) {
                    int toUse = feeData.getToUse();
                    if (toUse == 0) {

                        seaOriginMoney = seaOriginMoney.add(feeData.getPayMoney());
                        seaDiscountMoney = seaDiscountMoney.add(feeData.getPayMoney());
                        discountMoney = discountMoney.add(feeData.getPayMoney());
                    }
                }
            }
        }

        // 计算特权价
        List<String> specUsers = customerMapper.findSpecificUser();
        for (int i = 0; i < len; i++) {
            UserOrderSubs subOrder = new UserOrderSubs();

            subOrder.setId(UUIDGenerator.generate());
            subOrder.setCreateTime(date).setUpdateTime(date);
            subOrder.setOrdersId(orderId);

            CartOrderDso temps = myCart.get(i);
            String skuId = temps.getUnitId();
            List<Warehouse> warehouseList1 = repoWithWarehouse.get(skuId);


            int prodNum = (int) temps.getProdNum();
            subOrder.setProductId(temps.getProdId());
            subOrder.setProductNum(prodNum);
            subOrder.setUserId(userId);
            subOrder.setDeleted(0);
            subOrder.setIdCard(idCard);
            subOrder.setIsSwitch(0);
            subOrder.setSubsCodes(UUIDGenerator.generateOrderNo("PGSC"));
            subOrder.setExpressFree(temps.getExFee());
            subOrder.setToUseExpress(temps.getToUE());
            subOrder.setToUseTariff(temps.getToUG());

            String[] combineIds = two.get(skuId);
            // 名称
            StringBuilder sb = new StringBuilder();
            StringBuilder img = new StringBuilder();
            int a = 0;
            for (int ls = 0; ls < combineIds.length; ls++) {
                String s = three.get(combineIds[ls]);
                if (s != null) {
                    if (ls == combineIds.length - 1) {
                        sb.append(s);
                    } else {
                        sb.append(s + "、");
                    }
                }
                String imgUrls = four.get(combineIds[ls]);
                if (imgUrls != null && !"".equals(imgUrls)) {
                    img.append(imgUrls);
                    a = 1;
                } else if (a == 0 && ls == combineIds.length - 1 && (imgUrls == null || "".equals(imgUrls))) {
                    img.append(temps.getProdImg());
                }
            }
            String prodName = temps.getProdName();
            subOrder.setProductRemark(prodName + "|" + temps.getItemNo() + "|" + sb.toString());
            subOrder.setProductDiscount(temps.getDiscountNum());
            subOrder.setProdCurrentPrice(temps.getCp2());
            subOrder.setProductPrice(temps.getAttrPrice());
            if (!CollectionUtils.isEmpty(specUsers) && specUsers.contains(userId)) {
                BigDecimal minPrice = productMapper.findSkuSpecificMinPrice(skuId);
                if (minPrice != null) {
                    subOrder.setProdCurrentPrice(minPrice);
                    subOrder.setProductPrice(minPrice);
                    temps.setCp3(minPrice);
                }
            }

            int times = warehouseList1.size();

            for (int j = 0; j < times; j++) {
                Warehouse warehouse = warehouseList1.get(j);
                Integer nowNumber = warehouse.getNowNumber();
                WarehouseDetail warehouseDetail = new WarehouseDetail();
                warehouseDetail.setProductId(temps.getProdId());
                warehouseDetail.setOrdersId(orderId);
                warehouseDetail.setProductName(prodName);
                warehouseDetail.setProfiles(temps.getItemNo());
                warehouseDetail.setAttributeWithCategoryId(skuId);
                warehouseDetail.setOrderCodes(orderCodes);
                warehouseDetail.setSubsCodes(subOrder.getSubsCodes());
                warehouseDetail.setAttributeWithCategoryName(sb.toString());
                warehouseDetail.setProductMoney(five.get(skuId));
                warehouseDetail.setWarehouseBatch(warehouse.getWarehouseBatch());
                warehouseDetail.setNowCost(warehouse.getNowCost());
                warehouseDetail.setCreateTime(date);
                warehouseDetail.setUpdateTime(date);
                warehouseDetail.setStates(0);
                if (nowNumber >= prodNum) {
                    int st = prodNum;
                    warehouse.setNowNumber(nowNumber - st);
                    warehouseDetail.setId(UUIDGenerator.generate());
                    warehouseDetail.setProductNumber(prodNum);
                    warehouses.add(warehouse);
                    warehouseDetails.add(warehouseDetail);
                    break;
                } else {
                    prodNum = prodNum - nowNumber;
                    warehouseDetail.setId(UUIDGenerator.generate());
                    warehouseDetail.setProductNumber(nowNumber);
                    warehouse.setNowNumber(0);
                    warehouses.add(warehouse);
                    warehouseDetails.add(warehouseDetail);
                }

            }

            subOrder.setTariffFree(temps.getTariffFee());
            subOrder.setStates(0);

            BigDecimal subBill = temps.getCp2().multiply(BigDecimal.valueOf(temps.getProdNum()));
            subOrder.setSubBill(subBill);
            subOrder.setSubEnd(temps.getMi());


            subOrder.setZipCode(cartParam.getPostCode());
            subOrder.setSpecificImg(img.toString());
            String realName = cartParam.getRealName();
            if (StringUtils.isNotEmpty(realName)) {
                subOrder.setRealName(cartParam.getRealName());
            } else {
                if (address != null) {
                    subOrder.setRealName(address.getUserName());
                } else {
                    subOrder.setRealName("");
                }
            }
            //
            subOrder.setPayMoney(BigDecimal.ZERO);

            subOrders.add(subOrder);
        }


        UserOrder order = new UserOrder();
        order.setId(orderId).setCreateTime(date).setUpdateTime(date);
        order.setAddressId(addressId).setDeleted(0);
        order.setUserId(userId).setUserDiscount(1.0);
        order.setTariffFree(totalGateFee);
        order.setPayMoney(BigDecimal.ZERO);
        order.setProfitMoney(BigDecimal.ZERO);
        if (isOut == 1) {
            order.setGateExpressFee(exFee);
        } else {
            order.setGateExpressFee(BigDecimal.ZERO);
        }
        order.setTradeType(isOut);
        order.setOrdersCodes(orderCodes);
        order.setYunfei(exFee);
        if (userRank != null) {
            order.setUserDiscount(userRank.getUserDiscount().doubleValue());
        }
        order.setProdNum((int) prodtotal);
        order.setBillMoney(billMoney);
        order.setEndMoney(discountMoney);
        if (isOut == 1) {
            order.setEndMoney(seaDiscountMoney);
        }
        order.setOrderDiscount(orderDiscount.doubleValue());
        order.setStates(0);
        order.setRealMoney(soRealMoney);

        if (!CollectionUtils.isEmpty(specUsers) && specUsers.contains(userId)) {
            BigDecimal zero = BigDecimal.ZERO;
            for (CartOrderDso dso : myCart) {
                BigDecimal minPrice = dso.getCp3();
                if (minPrice != null) {
                    zero = zero.add(minPrice.multiply(BigDecimal.valueOf(dso.getProdNum())));
                }
            }
            if (zero.compareTo(BigDecimal.ZERO) > 0) {
                order.setEndMoney(zero);
                order.setOrderDiscount(1.0);
                order.setUserDiscount(1.0);
                order.setBillMoney(order.getEndMoney());
//                order.setYunfei(BigDecimal.ZERO);
//                order.setTariffFree(BigDecimal.ZERO);
                for (UserOrderSubs subOrder : subOrders) {

                    subOrder.setProductDiscount(1.0);
//                    subOrder.setExpressFree(BigDecimal.ZERO);
//                    subOrder.setTariffFree(BigDecimal.ZERO);
//                    subOrder.setProductPrice(minPrice);
                    subOrder.setSubEnd(order.getEndMoney());
                    subOrder.setSubBill(order.getEndMoney());
                }
            }

        }
        BigDecimal truthPayMoney = order.getEndMoney();
        subOrders.forEach(su -> {
                    su.setRealMoney(su.getSubEnd());
                    if (su.getToUseExpress() == 0) {
                        su.setRealMoney(su.getSubEnd().add(su.getExpressFree()));
                    }
                    if (su.getToUseTariff() == 0) {
                        su.setRealMoney(su.getSubEnd().add(su.getTariffFree()));
                    }
                }
        );
        UserOrderFinalInfo uof = new UserOrderFinalInfo();
        uof.setOrderId(orderId).setOrderNo(order.getOrdersCodes()).setNeedMoney(truthPayMoney)
                .setOrderMoney(truthPayMoney).setNeedPay(0);
        String cre = DateTimeUtils.formatLocalDate(order.getCreateTime());
        uof.setCreateTime(cre);


        // 我的账户
        UserProfit userProfitL1 = new UserProfit();
        if (account == 1 && isOut==0) {
            // 勾选余额付款
            UserProfitInfo userProfitInfo = customerMapper.selectUserProfit(userId);
            if (userProfitInfo != null) {
                BigDecimal canPay = userProfitInfo.getCanPay();
                // 充足,账户钱够用
                if (truthPayMoney.compareTo(canPay) <= 0) {
                    // 已经使用了货仓余额
                    userProfitL1.setId(userProfitInfo.getTemps());
                    userProfitL1.setProfitMoney(canPay.subtract(truthPayMoney));
                    userProfitL1.setUpdateTime(date);


                    order.setEndMoney(BigDecimal.ZERO);
                    order.setStates(1);
                    subOrders.forEach(su -> su.setStates(1));


                    truthPayMoney = truthPayMoney.setScale(2, BigDecimal.ROUND_HALF_UP);
                    uof.setNeedPay(1);
                    uof.setNeedMoney(BigDecimal.ZERO);


                    StringBuilder stringBuilder = new StringBuilder(Constants.rewardOrderPrefix);
                    stringBuilder.append(order.getUserId() + "_" + isOut).append(",")
                            .append(truthPayMoney).append(",")
                            .append(order.getId()).append(",")
                            .append(date.getTime()).append(",")
                            .append("profit");

//                    UserRankDetail down_profit = new UserRankDetail();
//                  延迟到支付返利后计算

                    UserGrowthDetail growInfo = new UserGrowthDetail();
                    growInfo.setCreateTime(date);
                    growInfo.setId(UUIDGenerator.generate());
                    growInfo.setGrowthValue(truthPayMoney.doubleValue());
                    growInfo.setUpMode(UpMode.SelfBuy);
                    growInfo.setOrdersId(orderId);
                    growInfo.setUserId(userId);
                    growInfo.setFromUserId(userId);
                    order.setFinishTime(date);
                    order.setProfitMoney(truthPayMoney);

                    userGrowthDetailMapper.insert(growInfo);
                    userProfitMapper.updateByIdSelective(userProfitL1);
                    order.setPayMoney(BigDecimal.ZERO);
                    int tempUseEx = 0;
                    int tempUseGa = 0;
                    for (UserOrderSubs su : subOrders) {
//                        su.setPayMoney(order.getPayMoney().multiply(su.getSubBill()).divide(order.getBillMoney(), 2, BigDecimal.ROUND_HALF_UP));
                        su.setProfitMoney(order.getProfitMoney().multiply(su.getSubBill()).divide(order.getBillMoney(), 2, BigDecimal.ROUND_HALF_UP));
                        su.setExpressFree(order.getYunfei().multiply(su.getSubBill()).divide(order.getBillMoney(), 2, BigDecimal.ROUND_HALF_UP));
                        su.setRealMoney(su.getSubEnd().subtract(su.getPayMoney()));
                        if (su.getToUseExpress() == 0) {
                            tempUseEx = su.getToUseExpress();
                            su.setRealMoney(su.getRealMoney().add(su.getExpressFree()));
                        }
                        if (su.getToUseTariff() == 0) {
                            tempUseGa = su.getToUseTariff();
                            su.setRealMoney(su.getRealMoney().add(su.getTariffFree()));
                        }
                    }
                    BigDecimal tempRealMoney = BigDecimal.ZERO;
                    if (tempUseEx == 0) {
                        tempRealMoney = order.getProfitMoney().subtract(order.getYunfei());
                        if (tempUseGa == 0) {
                            tempRealMoney = tempRealMoney.subtract(order.getTariffFree());
                        }
                    } else {
                        if (tempUseGa == 0) {
                            tempRealMoney = order.getProfitMoney().subtract(order.getTariffFree());
                        } else {
                            tempRealMoney = order.getProfitMoney();
                        }
                    }
                    order.setRealMoney(BigDecimal.ZERO);
                    // 订单倒计时,15秒后计算 等级收益
                    stringObjectRedisTemplate.opsForValue().set(stringBuilder.toString(), stringBuilder.toString(), 15, TimeUnit.SECONDS);
                    saveOrderAndSubsAndCart(order, subOrders, cartIds, warehouseList, warehouseDetails);
                    return uof;
                }
            }
        }
        truthPayMoney = truthPayMoney.setScale(2, BigDecimal.ROUND_HALF_UP);
        uof.setNeedMoney(truthPayMoney);
        uof.setOrderMoney(truthPayMoney);
        ValueOperations<String, String> opsForValue = stringRedisTemplate.opsForValue();
        opsForValue.set(Constants.lifestyleOrderPrefix + orderId, orderId, 6, TimeUnit.HOURS);
        saveOrderAndSubsAndCart(order, subOrders, cartIds, warehouseList, warehouseDetails);
        return uof;
    }

    /**
     * 立即购买类型
     *
     * @param once
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public UserOrderFinalInfo dealWithOnce(OnceParam once) {
        String skuId = once.getSkuId();
        String userId = once.getUserId();
        // 库存量
        long buyNum = once.getNum();
        String prodId = once.getProdId();
        String addressId = once.getAddressId();
        int account = once.getAccount();
        int usePay = once.getUse();
        String realName = once.getRealName();
        String idCard = once.getIdCard();

        Product product = productMapper.selectProdById(prodId);

        if (product == null || (product != null && product.getStates() == 1)) {
            throw new ParameterNullException("该商品已下架");
        }

        List<Warehouse> warehouseList = warehouseMapper.selectWarehouseInfo(skuId);
        if (CollectionUtils.isEmpty(warehouseList)) {
            throw new ParameterNullException("该商品不存在");
        }
        int totalStore = warehouseList.stream().mapToInt(s -> s.getNowNumber()).sum();
        if (totalStore == 0) {
            throw new NoSuchObjectException(402, "暂无库存 o(╥﹏╥)o");
        }
        if (totalStore < buyNum) {
            throw new NoSuchObjectException(402, "数量超过库存啦");
        }

        // 商品信息
        AttributeWithCategory prodAttribute = productMapper.selectAttributeWithCategoryById(skuId);

        HashMap<String, String[]> two = new HashMap<>();
        HashMap<String, String> three = new HashMap<>();
        HashMap<String, String> four = new HashMap<>();

        String allIds = prodAttribute.getAllAttributeValuesId();
        String[] split = allIds.split(",");
        List<String> allNameIds = Arrays.asList(split);

        two.put(prodAttribute.getId(), split);

        List<ProductAttributeValues> names = productMapper.selectProdNamesByAllIds(allNameIds);
        names.forEach(name -> {
            String cateImg = name.getCateImg();
            three.put(name.getId(), name.getCategoryValue());
            if (cateImg != null && cateImg != "") {
                four.put(name.getId(), name.getCateImg());
            }
        });
        String[] combineIds = two.get(once.getSkuId());
        // 名称
        StringBuilder sb = new StringBuilder();
        StringBuilder img = new StringBuilder();
        for (int ls = 0; ls < combineIds.length; ls++) {
            String imgUrls = four.get(combineIds[ls]);
            if (imgUrls != null) {
                img.append(imgUrls);
            }
            String s = three.get(combineIds[ls]);
            if (s != null) {
                if (ls != combineIds.length - 1) {
                    sb.append(s + "、");
                } else {
                    sb.append(s);
                }
            }
        }
        String prodName = product.getProductName();
        Integer inOrOut = product.getInOrOut();


        // 原始价格
        // todo 总价=数量*价格
        BigDecimal originMoney = prodAttribute.getPrice().multiply(BigDecimal.valueOf(buyNum));
//        List<ProductDiscount> discount = productMapper.selectProductDiscount(prodId);
        // sku的打折率
        List<ProdJoinDiscount> discounts = productMapper.selectProductSkuOneJoinDiscount(skuId);
        // todo  折后价
        BigDecimal discountMoney = originMoney;
        if (!CollectionUtils.isEmpty(discounts)) {
            ProdJoinDiscount dos = discounts.get(0);
            Integer cate = dos.getDiscountCate();
            //  0折扣种类1固定金额种类
            if (cate == 1) {
                discountMoney = dos.getDiscountNum().multiply(BigDecimal.valueOf(buyNum));
            } else {
                discountMoney = discountMoney.multiply(dos.getDiscountNum());
            }
        }

        BigDecimal billMoney = discountMoney;

        UserRankMoney userRank = userRankMapper.selectUserRankAndMoney(userId);
        UserAddress address = userAddressMapper.selectById(addressId);


        BigDecimal orderDiscount = BigDecimal.ONE;
        if (userRank != null) {
            // 用户折扣
            BigDecimal userDiscount = userRank.getUserDiscount();
            // 等级返利率
            BigDecimal rankInterest = userRank.getRankInterest();
            // 海外折扣
            BigDecimal seaRankRate = userRank.getSeaRankRate();


            // 不论是否为0,都计算
            discountMoney = discountMoney.multiply(userDiscount);

            if (rankInterest.compareTo(BigDecimal.ZERO) > 0) {
                if (inOrOut == 1) {
                    discountMoney = discountMoney.multiply(seaRankRate);
                    orderDiscount = seaRankRate;
                } else {
                    orderDiscount = rankInterest;
                    discountMoney = discountMoney.multiply(rankInterest);
                }
            }

        }
        // 关税
        BigDecimal rateMoney = BigDecimal.ZERO;
        List<ProductExtraInfo> productExtraInfos = productMapper.selectProdExtraInfo("");
        List<FeeData> data = productMapper.selectProductFeeData2();
        // 运费
        BigDecimal exFee = BigDecimal.ZERO;
        BigDecimal soRealMoney = discountMoney;
        int toUseGateSub = 1;
        int toUseExSub = 1;
        if (inOrOut == 1) {
            if (!CollectionUtils.isEmpty(data)) {
                BigDecimal fullMoney = data.get(0).getFullMoney();
                BigDecimal payMoney = data.get(0).getPayMoney();
                if (originMoney.compareTo(fullMoney) < 0) {
//                    originMoney = originMoney.add(payMoney);
                    int toUse = data.get(0).getToUse();
                    if (toUse == 0) {
                        discountMoney = discountMoney.add(payMoney);
                        exFee = payMoney;
                    }
                }
            }
        } else if (inOrOut == 2) {
            // todo  计算商品的 运费,关税
            if (!CollectionUtils.isEmpty(productExtraInfos)) {
                // todo
                List<ProductExtraInfo> collect = productExtraInfos.stream().filter(ll -> ll.getTradeType() == 2 && ll.getProvinceCode().equals(address.getCode())).collect(Collectors.toList());
                if (collect != null && collect.size() > 0) {
                    ProductExtraInfo otherFee = collect.get(0);
                    int toUse = otherFee.getToUse();
                    int toUse2 = otherFee.getToUse2();
                    // todo  关税
                    double chargesNumber = otherFee.getChargesNumber();
                    // todo 运费
                    BigDecimal chargesPrice = otherFee.getChargesPrice();
                    // todo 关税
                    rateMoney = BigDecimal.valueOf(chargesNumber).multiply(discountMoney);
                    exFee = chargesPrice;
                    // 需要交 运费
                    if (toUse != 1) {
                        discountMoney = discountMoney.add(chargesPrice);
                        toUseExSub = 0;
                    }

                    if (toUse2 != 1) {
                        discountMoney = discountMoney.add(rateMoney);
                        toUseGateSub = 0;
                    }

                }
            }
        } else if (inOrOut == 0) {
            // todo  计算商品的 运费,关税
            if (!CollectionUtils.isEmpty(productExtraInfos)) {
                // todo
                List<ProductExtraInfo> collect = productExtraInfos.stream().filter(ll -> ll.getTradeType() == 1 && ll.getProvinceCode().equals(address.getCode())).collect(Collectors.toList());
                if (collect != null && collect.size() > 0) {
                    ProductExtraInfo otherFee = collect.get(0);
                    int toUse = otherFee.getToUse();
                    int toUse2 = otherFee.getToUse2();


                    // todo  关税
                    double chargesNumber = otherFee.getChargesNumber();
                    // todo 运费
                    BigDecimal chargesPrice = otherFee.getChargesPrice();
                    // todo 关税
                    rateMoney = BigDecimal.valueOf(chargesNumber).multiply(discountMoney);
                    exFee = chargesPrice;
                    // 需要交 运费
                    if (toUse == 0) {
                        discountMoney = discountMoney.add(chargesPrice);
                        toUseExSub = 0;
                    }

                    if (toUse2 == 0) {
                        discountMoney = discountMoney.add(rateMoney);
                        toUseGateSub = 0;
                    }
                }
            }
        }


        String orderId = UUIDGenerator.generate();
        Date date = new Date();
        // todo 有用户等级
        UserOrderSubs subOrder = new UserOrderSubs();

        subOrder.setId(UUIDGenerator.generate());
        subOrder.setUserId(userId);
        subOrder.setCreateTime(date);
        subOrder.setUpdateTime(date);
        subOrder.setDeleted(0);
        subOrder.setTariffFree(rateMoney);
        subOrder.setStates(0);
        subOrder.setProductId(prodId);
        subOrder.setOrdersId(orderId);
        subOrder.setProductNum((int) buyNum);
        subOrder.setRealName(realName);
        subOrder.setIdCard(idCard);
        subOrder.setSubBill(billMoney);
        subOrder.setSubEnd(discountMoney);
        subOrder.setExpressFree(exFee);
        subOrder.setToUseTariff(toUseGateSub);
        subOrder.setToUseExpress(toUseExSub);
        subOrder.setIsSwitch(0);
        subOrder.setRealMoney(soRealMoney);
        subOrder.setPayMoney(BigDecimal.ZERO).setProfitMoney(BigDecimal.ZERO);

        if (StringUtils.isEmpty(realName)) {
            if (address == null) {
                subOrder.setRealName("");
            } else {
                subOrder.setRealName(address.getUserName());
            }
        }

        subOrder.setProductRemark(prodName + "|" + prodAttribute.getProfiles() + "|" + sb.toString());
        subOrder.setProductDiscount(0.0);
        BigDecimal price = prodAttribute.getPrice();
        if (!CollectionUtils.isEmpty(discounts)) {
            ProdJoinDiscount productDiscount = discounts.get(0);
            if (productDiscount.getDiscountCate() == 0) {
                subOrder.setProductDiscount(productDiscount.getDiscountNum().doubleValue());
                subOrder.setProdCurrentPrice(price.multiply(BigDecimal.valueOf(subOrder.getProductDiscount())));
            } else {
                // 一口价
                subOrder.setProductDiscount(-1.0);
                subOrder.setProdCurrentPrice(BigDecimal.valueOf(productDiscount.getDiscountNum().doubleValue()));
            }
        }
        subOrder.setProductPrice(price);


        subOrder.setSpecificImg(img.toString());
        subOrder.setSubsCodes(UUIDGenerator.generateOrderNo("DGSC"));

        UserOrder order = new UserOrder();
        order.setId(orderId);
        order.setCreateTime(date);
        order.setUpdateTime(date);
        order.setAddressId(addressId);
        order.setDeleted(0);
        order.setUserId(userId);
        order.setUserDiscount(1.0);
        order.setPayMoney(BigDecimal.ZERO);
        order.setProfitMoney(BigDecimal.ZERO);
        order.setTariffFree(rateMoney);
        if (inOrOut == 1) {
            order.setGateExpressFee(exFee);
        } else {
            order.setGateExpressFee(BigDecimal.ZERO);
        }
        order.setTradeType(inOrOut);
        order.setOrderDiscount(orderDiscount.doubleValue());
        order.setYunfei(exFee);
//        order.set
        order.setOrdersCodes(UUIDGenerator.generateOrderNo("DG"));
        if (userRank != null) {
            order.setUserDiscount(userRank.getUserDiscount().doubleValue());
        }
        order.setProdNum((int) buyNum);
        order.setProfitMoney(BigDecimal.ZERO)
                .setPayMoney(BigDecimal.ZERO);
        order.setBillMoney(billMoney);
        order.setEndMoney(discountMoney);
        order.setStates(0);
        order.setRealMoney(soRealMoney);
        //保存订单

        // 消耗库存
        // 次数
        int times = warehouseList.size();
        ArrayList<WarehouseDetail> warehouseDetails = new ArrayList<>();

        for (int i = 0; i < times; i++) {
            Warehouse warehouse = warehouseList.get(i);
            Integer nowNumber = warehouse.getNowNumber();
            WarehouseDetail warehouseDetail = new WarehouseDetail();
            warehouseDetail.setOrdersId(orderId);
            warehouseDetail.setProductId(prodId);
            warehouseDetail.setProductName(prodName);
            warehouseDetail.setProfiles(prodAttribute.getProfiles());
            warehouseDetail.setAttributeWithCategoryId(prodAttribute.getId());
            warehouseDetail.setOrderCodes(order.getOrdersCodes());
            warehouseDetail.setSubsCodes(subOrder.getSubsCodes());
            warehouseDetail.setAttributeWithCategoryName(sb.toString());
            warehouseDetail.setProductMoney(prodAttribute.getPrice());
            warehouseDetail.setWarehouseBatch(warehouse.getWarehouseBatch());
            warehouseDetail.setCreateTime(date);
            warehouseDetail.setNowCost(warehouse.getNowCost());
            warehouseDetail.setUpdateTime(date);
            warehouseDetail.setStates(0);
            if (nowNumber >= buyNum) {
                int st = (int) buyNum;
                warehouse.setNowNumber(nowNumber - st);
                warehouseDetail.setId(UUIDGenerator.generate());
                warehouseDetail.setProductNumber((int) buyNum);
                warehouseDetails.add(warehouseDetail);
                break;
            } else {
                buyNum = buyNum - nowNumber;
                warehouseDetail.setProductNumber(nowNumber);
                warehouseDetail.setId(UUIDGenerator.generate());
                warehouseDetails.add(warehouseDetail);
                warehouse.setNowNumber(0);
            }
        }

        // 计算特权价
        // 特权
        List<String> specUsers = customerMapper.findSpecificUser();
        BigDecimal minPrice = productMapper.findSkuSpecificMinPrice(skuId);
        if (!CollectionUtils.isEmpty(specUsers) && specUsers.contains(userId)) {
            if (minPrice != null) {
                subOrder.setProdCurrentPrice(minPrice);
                order.setEndMoney(minPrice.multiply(BigDecimal.valueOf(buyNum)));
                order.setOrderDiscount(1.0);
                order.setUserDiscount(1.0);
                order.setBillMoney(order.getEndMoney());
                subOrder.setProductDiscount(1.0);

                subOrder.setRealMoney(subOrder.getSubEnd());
                if (subOrder.getToUseTariff() == 0) {
                    subOrder.setRealMoney(subOrder.getRealMoney().add(subOrder.getTariffFree()));
                }
                if (subOrder.getToUseExpress() == 0) {
                    subOrder.setRealMoney(subOrder.getRealMoney().add(subOrder.getExpressFree()));
                }
//                subOrder.setExpressFree(BigDecimal.ZERO);
//                subOrder.setTariffFree(BigDecimal.ZERO);
//                subOrder.setProductPrice(minPrice);
                subOrder.setSubEnd(order.getEndMoney());
                subOrder.setSubBill(order.getEndMoney());
            }
        }
        BigDecimal truthPayMoney = order.getEndMoney();

        UserOrderFinalInfo uof = new UserOrderFinalInfo();
        uof.setOrderId(orderId).setOrderNo(order.getOrdersCodes())
                .setOrderMoney(truthPayMoney).setNeedPay(0).setNeedMoney(truthPayMoney);
        String cre = DateTimeUtils.formatLocalDate(order.getCreateTime());
        uof.setCreateTime(cre);


        UserProfit userProfitL1 = new UserProfit();


        if (account == 1 && product.getInOrOut()==0) {
            // 勾选余额付款
            UserProfitInfo userProfitInfo = customerMapper.selectUserProfit(userId);
            if (userProfitInfo != null) {
                BigDecimal canPay = userProfitInfo.getCanPay();
                // 充足,账户钱够用
                if (truthPayMoney.compareTo(canPay) <= 0) {
                    // 已经使用了货仓余额
                    userProfitL1.setId(userProfitInfo.getTemps());
                    userProfitL1.setProfitMoney(canPay.subtract(truthPayMoney));
                    userProfitL1.setUpdateTime(date);


                    order.setEndMoney(BigDecimal.ZERO);
                    order.setStates(1);
                    subOrder.setStates(1);


                    uof.setNeedPay(1);
                    uof.setNeedMoney(BigDecimal.ZERO);
                    uof.setOrderMoney(BigDecimal.ZERO);


                    StringBuilder stringBuilder = new StringBuilder(Constants.rewardOrderPrefix);
                    stringBuilder.append(order.getUserId() + "_" + inOrOut).append(",")
                            .append(truthPayMoney).append(",")
                            .append(order.getId()).append(",")
                            .append(date.getTime()).append(",")
                            .append("profit");

//                    UserRankDetail down_repo = new UserRankDetail();
//    延迟到 结算后统一发放返利


                    UserGrowthDetail growInfo = new UserGrowthDetail();
                    growInfo.setCreateTime(date);
                    growInfo.setId(UUIDGenerator.generate());
                    growInfo.setGrowthValue(truthPayMoney.doubleValue());
                    growInfo.setUpMode(UpMode.SelfBuy);
                    growInfo.setOrdersId(orderId);
                    order.setFinishTime(date);
                    growInfo.setUserId(userId);
                    growInfo.setFromUserId(userId);
                    order.setProfitMoney(truthPayMoney);
                    subOrder.setRealMoney(BigDecimal.ZERO);

                    subOrder.setPayMoney(BigDecimal.ZERO).setRealMoney(BigDecimal.ZERO);
                    order.setPayMoney(BigDecimal.ZERO);

                    BigDecimal tempRealMoney = BigDecimal.ZERO;
                    if (subOrder.getToUseExpress() == 0) {
                        tempRealMoney = order.getProfitMoney().subtract(order.getYunfei());
                        if (subOrder.getToUseTariff() == 0) {
                            tempRealMoney = tempRealMoney.subtract(order.getTariffFree());
                        }
                    } else {
                        if (subOrder.getToUseTariff() == 0) {
                            tempRealMoney = order.getProfitMoney().subtract(order.getTariffFree());
                        } else {
                            tempRealMoney = order.getProfitMoney();
                        }
                    }
                    order.setRealMoney(BigDecimal.ZERO);

                    userGrowthDetailMapper.insert(growInfo);
                    userProfitMapper.updateByIdSelective(userProfitL1);

                    // 订单倒计时,15秒后计算 等级收益
                    stringObjectRedisTemplate.opsForValue().set(stringBuilder.toString(), stringBuilder.toString(), 15, TimeUnit.SECONDS);
                    saveOrderAndSubsAndCart(order, subOrder, warehouseList, warehouseDetails);
                    return uof;
                }
            }
        }

        truthPayMoney = truthPayMoney.setScale(2, BigDecimal.ROUND_HALF_UP);
        uof.setNeedMoney(truthPayMoney);
        uof.setOrderMoney(truthPayMoney);
        ValueOperations<String, String> opsForValue = stringRedisTemplate.opsForValue();
        opsForValue.set(Constants.lifestyleOrderPrefix + orderId, orderId, 6, TimeUnit.HOURS);
        saveOrderAndSubsAndCart(order, subOrder, warehouseList, warehouseDetails);
        return uof;
    }


    @Transactional(rollbackFor = Exception.class)
    public int saveOrderAndSubsAndCart(UserOrder userOrder, List<UserOrderSubs> subs, List<String> cartIds, List<Warehouse> warehouses, List<WarehouseDetail> warehouseDetails) {
        int one = userOrderMapper.insertMainOrder(userOrder);
        int more = customerMapper.batchInsertSubOrders(subs);
        customerMapper.hiddenUserCartByIds(cartIds, userOrder.getCreateTime());
        warehouseMapper.batchUpdateWarehouse(warehouses);
        warehouseMapper.batchInsertWarehouseDetail(warehouseDetails);
        applicationContext.publishEvent(new PatchProdEvent(warehouses));
        return one + more;
    }

    @Transactional(rollbackFor = Exception.class)
    public int saveOrderAndSubsAndCart(UserOrder userOrder, UserOrderSubs subs, List<Warehouse> warehouses, List<WarehouseDetail> warehouseDetails) {
        int one = userOrderMapper.insertMainOrder(userOrder);
        int more = userOrderMapper.insertSubOrder(subs);
        warehouseMapper.batchUpdateWarehouse(warehouses);
        warehouseMapper.batchInsertWarehouseDetail(warehouseDetails);
        applicationContext.publishEvent(new PatchProdEvent(warehouses));
        return one + more;
    }


    /**
     * 0 查询异常
     * 1 暂无记录
     * 2 在途中
     * 3 派送中
     * 4 已签收
     * 5 用户拒签
     * 6 疑难件
     * 7 无效单
     * 8 超时单
     * 9 签收失败
     * 10 退回
     */
    public ExpressInfos findNewExpressInfo(String orderId, String subsOrderId, String expressAbbr, String subsCodes, String expressCodes) {
        ExpressInfos expressDto = userOrderMapper.selectOrderExpressInfo(subsCodes);
        if (expressDto == null || (expressDto != null && expressDto.getStates() != 4)) {
            Map<String, String> headers = new HashMap<String, String>();
            headers.put("Authorization", "APPCODE " + appCode);
            Map<String, String> querys = new HashMap<>();
            querys.put("nu", expressCodes);
            if (expressAbbr != null) {
                querys.put("com", expressAbbr);
                if (expressAbbr.equals("shufeng")) {
                    querys.put("receiverPhone", "");
                }
            } else {
                querys.put("com", "auto");
            }
            String res = HttpClientUtil.getRequest(expressAddress, querys, headers);
            logger.info("调用第三方接口【快递查询】返回数据 {}", res);
            JSONObject express = JSONObject.parseObject(res);
            ExpressInfos dto = new ExpressInfos();
            dto.setId(UUIDGenerator.generate()).setSubCodes(subsCodes);
            JSONObject res_body = express.getJSONObject("showapi_res_body");
            int retCode = res_body.getIntValue("ret_code");
            if (retCode == 0) {
                int status = res_body.getIntValue("status");
                JSONArray data = res_body.getJSONArray("data");
                dto.setStates(status);
                dto.setContents(data.toJSONString());
                dto.setExpressCode(expressCodes);
                if (status == 4) {
                    Date date = new Date();
                    UserOrderSubs userOrderSubs = new UserOrderSubs();
                    userOrderSubs.setId(subsOrderId);
                    userOrderSubs.setUpdateTime(date);
                    userOrderSubs.setStates(3);
                    userOrderMapper.updateSubsByIdSelective(userOrderSubs);
                }

            } else {
                List<ExpressArrayInfo> list = new ArrayList<>();
                dto.setStates(4);
                ExpressArrayInfo expressContent = new ExpressArrayInfo();
                SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                String data = simpleDateFormat.format(new Date());
                expressContent.setTime(data);
                expressContent.setContext("未找到物流信息");
                list.add(expressContent);
                String parseArray = JSON.toJSONString(list);
                dto.setContents(parseArray);
                dto.setExpressCode(expressCodes);
            }
            if (expressDto == null) {
                userOrderMapper.insertExpress(dto);
            } else {
                dto.setId(expressDto.getId());
                userOrderMapper.updateExpressDto(dto);
            }
            String contents = dto.getContents();
            if (StringUtils.isNotEmpty(contents)) {
                List<ExpressArrayInfo> infos = JSONArray.parseArray(contents, ExpressArrayInfo.class);
                dto.setCnt(infos);
            }
            return dto;
        }
        String contents = expressDto.getContents();
        if (StringUtils.isNotEmpty(contents)) {
            List<ExpressArrayInfo> infos = JSONArray.parseArray(contents, ExpressArrayInfo.class);
            expressDto.setCnt(infos);
        }
        return expressDto;
    }


}
